﻿
using Prism.Ioc;
using Prism.Modularity;
using Prism.Unity;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using RestSharp;
using WpfRedis.Common;
using System.Windows.Markup;
using Microsoft.Practices.Unity.Configuration;
using WpfRedis.Views;
using WpfRedis.ViewModels;
using MS.Common.Helpers;
using JHWpfToolkit;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using Mqtt;
using MQTTnet.Client.Options;
using System.Threading;
using System.Text;

namespace WpfRedis
{
    /// <summary>
    /// App.xaml 的交互逻辑
    /// </summary>
    public partial class App : PrismApplication
    {
        private readonly string fileModuleInfo = AppDomain.CurrentDomain.BaseDirectory + "ModuleCatalog.xaml";
        MyDirectoryModuleCatalog Catlog;
        public App()
        {
            this.Startup += App_Startup;
        }
        Mutex mutex;
        private void App_Startup(object sender, StartupEventArgs e)
        {
            bool ret;
            mutex = new Mutex(true, "WpfRedis", out ret);
            if (!ret)
            {
                MessageBox.Show("只允许启动一个实例");
                Environment.Exit(0);
               
            }
        }

        protected override void OnInitialized()
        {
            #region 全局异常事件配置
            // 在异常由应用程序引发但未进行处理时发生，但无法捕获多线程异常
            // UI线程中的异常 UnhandledException 和  DispatcherUnhandledException 都会捕获 执行顺序是 DispatcherUnhandledException => UnhandledException
            this.DispatcherUnhandledException += App_DispatcherUnhandledException;
            // 专门捕获所有线程中的异常 
            AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
            // 专门捕获Task异常
            TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
            #endregion

         
            base.OnInitialized(); 
        }

        /// <summary>
        /// 全局异常
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void App_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
        {
            LogHelper.GetLogHelper().Error(e.Exception.Message);
            e.Handled = true;
        }

        private void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
        {
            LogHelper.GetLogHelper().Error(e.Exception);
            e.SetObserved();//设置该异常已察觉（这样处理后就不会引起程序崩溃）
        }

        private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            StringBuilder sbEx = new StringBuilder();
            if (e.IsTerminating)
            {
                sbEx.Append("非UI线程发生致命错误");
            }
            sbEx.Append("非UI线程异常：");
            if (e.ExceptionObject is Exception)
            {
                sbEx.Append(((Exception)e.ExceptionObject).ToString());
            }
            else
            {
                sbEx.Append(e.ExceptionObject);
            }
            LogHelper.GetLogHelper().Error(sbEx.ToString());
            //在.Net6.0中无效 --- 在 app.config <runtime> 节点下添加 <legacyUnhandledExceptionPolicy enabled="1"/> 可以阻止应用程序奔溃类似 e.Handle=true

        }
 

        /// <summary>
        /// 1从文件中初始化模块
        /// </summary>
        /// <returns></returns>
        protected override IModuleCatalog CreateModuleCatalog()
        {
            if (File.Exists(fileModuleInfo))//已经生成的有xaml文件映射关系
            {

                using (FileStream fs = new FileStream(fileModuleInfo, FileMode.Open))
                {
                    return ModuleCatalog.CreateFromXaml(fs);
                }
            }
            else
            {
                //没有模块映射关系，需要反射自己创建返回
                Catlog = new MyDirectoryModuleCatalog() { ModulePath = AppDomain.CurrentDomain.BaseDirectory + "Modules" };
                return Catlog;
            }
        }
       
        /// <summary>
        /// 指定主界面
        /// </summary>
        /// <returns></returns>
        protected override Window CreateShell()
        {
            //return Container.Resolve<AppMainView>();
            //new ParameterOverride("singleSignArgs", this.args)LoginWindow MainWindow
            return Container.Resolve<LoginView>();
        }

        protected override void InitializeModules()
        {
            base.InitializeModules();
            if (Catlog != null)
            {
                ModuleCatalogConfigXAML xml = new ModuleCatalogConfigXAML(Catlog);
                xml.GenerateXAMLConfigFile(fileModuleInfo);
            }
            LoadResourceDictionary();
        }

        protected override void InitializeShell(Window Shell)
        {
            try
            {
                Application.Current.MainWindow = (Window)Shell;
                if (Application.Current.MainWindow != null)
                {
                    Application.Current.MainWindow.Show();
                }
            }
            catch (Exception ex)
            {
                LogHelper.GetLogHelper().Error("在启动项中监听到异常信息");
                LogHelper.GetLogHelper().Error(ex);
            }

        }
        /// <summary>
        /// 注册进容器
        /// </summary>
        /// <param name="containerRegistry"></param>
        protected override void RegisterTypes(IContainerRegistry containerRegistry)
        {
            string appjsonPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "App.json");
            string json = File.ReadAllText(appjsonPath);
            JObject jobject = JsonConvert.DeserializeObject<JObject>(json);

            // MqttClientTcpOptions options = jobject.GetValue("Mqtt").ToObject<MqttClientTcpOptions>();
            //containerRegistry.RegisterInstance(typeof(MQTTClients), new MQTTClients(options));
            containerRegistry.Register<AppMainViewModel>();
            containerRegistry.Register<LoginViewModel>();
            containerRegistry.Register<AppMainView>();
            containerRegistry.Register<LoginView>();
            containerRegistry.Register<Object, WebView>(nameof(WebView));
            containerRegistry.RegisterInstance<Notifiaction>(new Notifiaction());
            IRestClient client = new RestClientBase() { Authenticator = new Authenticator() { } };
            containerRegistry.RegisterInstance<IRestClient>(client);
            containerRegistry.RegisterInstance<RedisHelper>(new RedisHelper());

            string configPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "otherConfig.config");
            //加载配置文件
            Configuration config = ConfigurationManager.OpenMappedExeConfiguration(new ExeConfigurationFileMap() { ExeConfigFilename = configPath }, ConfigurationUserLevel.None);
            UnityConfigurationSection section = (UnityConfigurationSection)config.GetSection("unity");
            section?.Configure(containerRegistry.GetContainer());
            //https://blog.csdn.net/qq_29821795/article/details/116504693
        }
        /// <summary>
        /// 加载主题
        /// </summary>
        private void LoadResourceDictionary()
        {
            try
            {
                var path = AppDomain.CurrentDomain.BaseDirectory + "Themes";
                if (Directory.Exists(path))
                {
                    DirectoryInfo directory = new DirectoryInfo(path);
                    var fileInfos = directory.GetFiles("*.xaml");
                    if (fileInfos.Length == 0)
                    {
                        return;
                    }
                    foreach (var file in fileInfos)
                    {
                        try
                        {
                            using (FileStream fs = new FileStream(file.FullName, FileMode.Open))
                            {
                                ResourceDictionary dic = (ResourceDictionary)XamlReader.Load(fs);

                                Application.Current.Resources.MergedDictionaries.Add(dic);
                            }
                        }
                        catch (Exception ex)
                        {
                            LogHelper.GetLogHelper().Error(ex);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                LogHelper.GetLogHelper().Error(ex);
            }
        }

    }
}

